// 多继承
// 思路：利用深/浅拷贝，将属性复制，不存在instanceof关系

// 1 extend 单继承 属性复制
var extend = function(target, source) {
  // 便利源对象的属性
  for (var property in source) {
    // 将源对象属性复制到目标对象中
    // 浅复制，不能复制引用类型
    target[property] = source[property];
  }
  // 返回目标对象
  return target;
}


// 2 mix 多继承
var mix = function() {
  var i = 1,                  // 从第二个参数起为被继承的源对象
      len = arguments.length, // 获取参数长度
      target = arguments[0],  // 第一个对象为目标对象
      arg;                    // 缓存参数对象
  // 遍历被继承对象
  for (; i < len; i++) {
    // 缓存当前对象
    arg = arguments[i];
    // 遍历被继承对象中的属性
    for (var property in arg) {
      // 将被继承对象中的属性复制到目标对象中
      target[property] = arg[property];
    }
  }
  // 返回目标对象
  return target;
}

// 2.1 改进 深复制
var mix = function() {
  var i = 1,                  // 从第二个参数起为被继承的源对象
      len = arguments.length, // 获取参数长度
      target = arguments[0],  // 第一个对象为目标对象
      arg,                    // 缓存参数对象
      toString = Object.prototype.toString;
  // 遍历被继承对象
  for (; i < len; i++) {
    // 缓存当前对象
    arg = arguments[i];
    // 遍历被继承对象中的属性
    for (var prop in arg) {
      // 排除原型链上的属性
      if (arg.hasOwnProperty(prop)) {
        // 使用typeof判断是都是引用类型
        if (arg[prop] !== null && typeof(arg[prop]) === 'object') {
          // Object.prototype.call([])判断是[]还是{}
          if (toString.call(arg[prop]) === '[object Array]') {
            target[prop] = [];
          } else {
            target[prop] = {};
          }
          mix(target[prop], arg[prop]); // 递归
        } else {
          target[prop] = arg[prop];
        }
      }
    }
  }
  // 返回目标对象
  return target;
}

// 3 改进 放些加到Object原型链上
Object.prototype.mix = function() {
  var i = 0,
      len = arguments.length,
      arg,
      toString = Object.prototype.toString;
  for (; i < len; i++) {
    arg = arguments[i];
    for (var prop in arg) {
      if (arg.hasOwnProperty(prop)) {
        if (arg[prop] !== null && typeof(arg[prop]) === 'object') {
          if (toString.call(arg[prop]) === '[object Array]') {
            this[prop] = [];
          } else {
            this[prop] = {};
          }
          this[prop].mix(arg[prop]);
        } else {
          this[prop] = arg[prop];
        }
      }
    }
  }
}



// 测试
function Super() {
  this.name = 'js book';
  this.books = ['css', 'java'];
}
Super.prototype.show = function() {}
var obj = {};
obj.mix(new Super());
